package com.wkk.authentication.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.wkk.annotation.AutoLog;
import com.wkk.authentication.dto.UserLoginDto;
import com.wkk.authentication.entity.UmsUser;
import com.wkk.authentication.service.UmsUserService;
import com.wkk.constant.CommonConstant;
import com.wkk.log.common.LogConstant;
import com.wkk.utils.JwtUtil;
import com.wkk.utils.NoBugTools;
import com.wkk.utils.PasswordUtil;
import com.wkk.utils.RedisUtil;
import com.wkk.vo.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;

/**
 * @author : WangKeKe
 * @date : 2020/9/12 9:47
 * Description :
 */

@RestController
@Slf4j
@RequestMapping("/ums/user")
@Api(tags = "RESTFUL-用户-登录注册")
public class UmsUserController {

    @Autowired
    private UmsUserService umsUserService;

    @Autowired
    private RedisUtil redisUtil;

    @AutoLog(description = LogConstant.ROLE_NAME_USER + "-账号登录")
    @ApiOperation("用户-账号登录")
    @PostMapping("/login")
    public Result<String> umsUserLogin(@RequestBody @Validated UserLoginDto userLoginDto,
                                       HttpServletResponse response) {
        UmsUser user = umsUserService.getOne(new LambdaQueryWrapper<UmsUser>()
                .eq(UmsUser::getUsername, userLoginDto.getUsername()));
        if (NoBugTools.isEmpty(user)) {
            return Result.error("当前用户不存在");
        }
        // 将当前输入密码 MD5加盐 加密
        String md5Password = PasswordUtil.encrypt(userLoginDto.getUsername(), userLoginDto.getPassword(), user.getSalt());
        if (!md5Password.equals(user.getPassword())) {
            return Result.error("密码错误！");
        }
        // 获取当前时间戳
        String currentTimeMillis = String.valueOf(System.currentTimeMillis());
        // 创建/覆盖 该用户ID所对应的refresh_token信息 生命周期为60min
        redisUtil.set(CommonConstant.PREFIX_SHIRO_REFRESH_TOKEN + user.getId(), currentTimeMillis, CommonConstant.REFRESH_TOKEN_TIME);
        // 创建token (时间戳、和refresh_token一样的时间戳，过期时间戳)
        String token = JwtUtil.sign(user.getId(), md5Password, currentTimeMillis);
        // 将token放入 返回头的X_ACCESS_TOKEN中
        response.setHeader(CommonConstant.X_ACCESS_TOKEN, token);
        response.setHeader("Access-Control-Expose-Headers", CommonConstant.X_ACCESS_TOKEN);
        return Result.ok("登录成功");
    }

    @AutoLog(description = LogConstant.ROLE_NAME_USER + "-账号注册")
    @ApiOperation("用户-账号注册")
    @PostMapping("/register")
    public Result<String> umsUserRegister(@RequestBody @Validated UserLoginDto userLoginDto) {
        // 由于字段做了后端验证所以这里无需判空
        UmsUser umsUser = umsUserService.getOne(new LambdaQueryWrapper<UmsUser>()
                .eq(UmsUser::getUsername, userLoginDto.getUsername()));
        if (NoBugTools.isNotEmpty(umsUser)) {
            return Result.error("该用户名已被注册");
        }
        return umsUserService.accountRegister(userLoginDto) ? Result.ok("注册成功") : Result.error("注册失败");
    }

    @AutoLog(description = LogConstant.ROLE_NAME_USER + "-账号退出")
    @ApiOperation("用户-账号退出")
    @DeleteMapping("/logout")
    public Result<String> umsUserLogout() {
        Subject subject = SecurityUtils.getSubject();
        UmsUser umsUser = (UmsUser) subject.getPrincipal();
        String refreshTokenKey = CommonConstant.PREFIX_SHIRO_REFRESH_TOKEN + umsUser.getId();
        redisUtil.del(refreshTokenKey);
        subject.logout();
        return Result.ok("退出成功");
    }

    @AutoLog(description = LogConstant.ROLE_NAME_USER + "-登录信息")
    @ApiOperation("用户-登录信息")
    @GetMapping("/info")
    public Result<UmsUser> userResult() {
        // 在认证的时候，已经将用户信息存入Subject中 故可以通过其获取当前用户信息
        Subject subject = SecurityUtils.getSubject();
        return Result.ok((UmsUser) subject.getPrincipal());
    }
}
